import type { VotesResponse, VoteResponse } from '../types/vote';

const API_BASE_URL = 'https://server.illli.cc/api';

const getAuthToken = (): string | null => {
  return localStorage.getItem('auth_token');
};

const createHeaders = (): HeadersInit => {
  const token = getAuthToken();
  const headers: HeadersInit = {
    'Content-Type': 'application/json',
  };
  if (token) headers.Authorization = `Bearer ${token}`;
  return headers;
};

const handleResponse = async (response: Response) => {
  if (!response.ok) {
    const errorData = await response.json().catch(() => ({ message: 'Network error' }));
    throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
  }
  return response.json();
};

// 标准化 vote/drawing 的 users 字段为 user，兼容前端类型
const normalizeUsers = (obj: any) => {
  if (obj) {
    // Vote: 后端可能为 user（单数）或 users（复数），统一为 user
    if (obj.users && !obj.user) obj.user = Array.isArray(obj.users) ? obj.users[0] : obj.users;
    if (obj.drawing) {
      const d = obj.drawing;
      if (d?.users && !d.user) d.user = Array.isArray(d.users) ? d.users[0] : d.users;
    }
  }
  return obj;
};

const normalizeVotesPayload = <T = any>(payload: T): T => {
  const p: any = payload as any;
  if (p && p.data !== undefined) {
    if (Array.isArray(p.data)) {
      p.data = p.data.map((v: any) => normalizeUsers(v));
    } else if (p.data && typeof p.data === 'object') {
      p.data = normalizeUsers(p.data);
    }
  }
  return p as T;
};

// 读取单条投票（用于回读 ensure 结果）
const fetchVoteById = async (id: number, documentId?: string): Promise<VoteResponse> => {
  // 在Strapi v5中，优先使用documentId，如果没有则尝试使用数字ID
  const identifier = documentId || id;
  const url = `${API_BASE_URL}/votes/${identifier}?populate=*`;
  
  const resp = await fetch(url, {
    method: 'GET',
    headers: createHeaders(),
  });
  const result: VoteResponse = await handleResponse(resp);
  return normalizeVotesPayload<VoteResponse>(result);
};

// 获取集合类型条目的 documentId（v5），若无则回退为数字 id
const getDocumentIdentifier = async (collection: 'drawings' | 'votes' | 'users', id: number): Promise<string | number> => {
  try {
    // 统一使用列表查询，避免 /:id 造成 404；并且仅请求需要的字段
    const params = new URLSearchParams({
      'filters[id][$eq]': id.toString(),
      'fields[0]': 'documentId',
      'fields[1]': 'id',
      'pagination[page]': '1',
      'pagination[pageSize]': '1',
    });
    const resp = await fetch(`${API_BASE_URL}/${collection}?${params.toString()}`, {
      method: 'GET',
      headers: createHeaders(),
    });
    const data = await handleResponse(resp);

    // 兼容不同集合返回结构：
    // - 通用集合（drawings/votes）：{ data: [{ id, documentId, ... }] }
    // - 用户集合（/users）：[{ id, documentId? , ... }]
    let node: any = null;
    if (Array.isArray(data)) {
      node = data[0];
    } else if (Array.isArray((data as any)?.data)) {
      node = (data as any).data[0];
    } else {
      node = (data as any)?.data ?? data;
    }

    return node?.documentId || node?.id || id;
  } catch {
    return id;
  }
};

// 使用 v5 关系 connect / set 语法确保绑定
const tryConnectRelation = async (
  voteIdentifier: string | number,
  relField: 'drawing' | 'user',
  targetIdentifier: string | number
): Promise<boolean> => {
  const key = typeof targetIdentifier === 'string' ? 'documentId' : 'id';
  const candidates: Record<string, any>[] = [
    // v5 推荐：connect（数组）
    { [relField]: { connect: [{ [key]: targetIdentifier }] } },
    // v5：set（重置为该关系）
    { [relField]: { set: [{ [key]: targetIdentifier }] } },
    // 兼容：直接给数字/数组（v4旧式）
    { [relField]: targetIdentifier },
    { [relField]: [targetIdentifier] },
  ];

  for (const data of candidates) {
    try {
      const resp = await fetch(`${API_BASE_URL}/votes/${voteIdentifier}`, {
        method: 'PUT',
        headers: createHeaders(),
        body: JSON.stringify({ data }),
      });
      if (resp.ok) return true;
    } catch {
      // 尝试下一种形态
    }
  }
  return false;
};

// 确保把投票与画作建立关联
const ensureDrawingAssociation = async (voteId: number, drawingId: number): Promise<void> => {
  const voteIdentifier = await getDocumentIdentifier('votes', voteId);
  const drawingIdentifier = await getDocumentIdentifier('drawings', drawingId);
  await tryConnectRelation(voteIdentifier, 'drawing', drawingIdentifier);
};

// 确保把投票与用户建立关联
const ensureUserAssociation = async (voteId: number, userId: number): Promise<void> => {
  const voteIdentifier = await getDocumentIdentifier('votes', voteId);
  const userIdentifier = await getDocumentIdentifier('users', userId);
  await tryConnectRelation(voteIdentifier, 'user', userIdentifier);
};

// 检查用户是否对某个画作投过票（移除populate参数避免role字段错误）
export const checkUserVote = async (userId: number, drawingId: number): Promise<boolean> => {
  try {
    const paramsUser = new URLSearchParams({
      'filters[user][id][$eq]': userId.toString(),
      'filters[drawing][id][$eq]': drawingId.toString(),
      'pagination[page]': '1',
      'pagination[pageSize]': '1'
    });

    const resp1 = await fetch(`${API_BASE_URL}/votes?${paramsUser}`, {
      method: 'GET',
      headers: createHeaders(),
    });
    const result1: VotesResponse = await handleResponse(resp1);
    const normalized1 = normalizeVotesPayload<VotesResponse>(result1);
    return Array.isArray(normalized1?.data) && normalized1.data.length > 0;
  } catch (error) {
    console.error('检查投票状态失败:', error);
    // 如果检查失败，默认返回false，允许用户尝试投票
    return false;
  }
};

// 更新Drawing的votes关联（通常不需要，关系是双向的，但保留兜底逻辑）
const updateDrawingVotes = async (drawingId: number, voteId: number): Promise<void> => {
  try {
    // 直接进行 connect，而不再读取 drawing 明细（避免 populate[*] 触发 v5 校验错误）
    const voteIdentifier = await getDocumentIdentifier('votes', voteId);
    const voteKey = typeof voteIdentifier === 'string' ? 'documentId' : 'id';

    await fetch(`${API_BASE_URL}/drawings/${drawingId}`, {
      method: 'PUT',
      headers: createHeaders(),
      body: JSON.stringify({
        data: {
          votes: { connect: [{ [voteKey]: voteIdentifier }] }
        }
      }),
    }).catch(() => {});
  } catch (error) {
    console.warn('Error updating drawing votes:', error);
  }
};

export const voteForDrawing = async (userId: number, drawingId: number): Promise<VoteResponse> => {
  try {
    // 先检查是否已经投过票
    const hasVoted = await checkUserVote(userId, drawingId);
    if (hasVoted) {
      throw new Error('您已经为这个作品投过票了');
    }

    // 预取用于 v5 connect 的 documentId（或回退为数字 id）
    const [userIdentifier, drawingIdentifier] = await Promise.all([
      getDocumentIdentifier('users', userId),
      getDocumentIdentifier('drawings', drawingId),
    ]);

    const userKey = typeof userIdentifier === 'string' ? 'documentId' : 'id';
    const drawingKey = typeof drawingIdentifier === 'string' ? 'documentId' : 'id';
    const userConnect = { [userKey]: userIdentifier } as Record<string, string | number>;
    const drawingConnect = { [drawingKey]: drawingIdentifier } as Record<string, string | number>;

    // 尝试两种兼容数据格式（优先 v5 connect 语法），去除无效字段
    const bodyFormats = [
      {
        data: {
          // publishedAt 字段去除，避免后端校验失败
          user: { connect: [userConnect] },
          drawing: { connect: [drawingConnect] },
        },
      },
      {
        data: {
          user: userId,
          drawing: drawingId,
          // publishedAt 去除
        },
      },
    ];

    let lastError: any = null;
    let createdVote: any = null;
    
    for (const bodyData of bodyFormats) {
      try {
        const response = await fetch(`${API_BASE_URL}/votes`, {
          method: 'POST',
          headers: createHeaders(),
          body: JSON.stringify(bodyData),
        });
        
        if (response.ok) {
          const result: VoteResponse = await response.json();
          
          // 立即重新获取投票数据，使用populate参数获取完整的关联数据
          const voteId = (result as any).data?.id;
          const documentId = (result as any).data?.documentId;
          if (voteId && documentId) {
            try {
              const fullVoteData = await fetchVoteById(voteId, documentId);
              createdVote = fullVoteData;
            } catch {
              createdVote = normalizeVotesPayload<VoteResponse>(result);
            }
          } else {
            createdVote = normalizeVotesPayload<VoteResponse>(result);
          }
          
          // 验证关联是否正确设置（兜底 ensure）
          const v: any = createdVote?.data;
          if (v) {
            if (!v.drawing || (typeof v.drawing === 'object' && v.drawing?.id !== drawingId)) {
              try { await ensureDrawingAssociation(v.id, drawingId); } catch {}
            }
            if (!v.user || (typeof v.user === 'object' && v.user?.id !== userId)) {
              try { await ensureUserAssociation(v.id, userId); } catch {}
            }
            try { await updateDrawingVotes(drawingId, v.id); } catch {}
          }
          
          return createdVote;
        } else {
          // 改进错误信息提取，便于定位400的具体原因
          let message = `HTTP ${response.status}: 投票失败`;
          try {
            const errorData = await response.json();
            const m = (errorData && (errorData.message || errorData.error?.message || errorData.error?.details || errorData.error)) as string | undefined;
            if (m) message = m;
          } catch {
            try {
              const text = await response.text();
              if (text) message = text;
            } catch {}
          }
          lastError = new Error(message);
        }
      } catch (error) {
        lastError = error;
        continue; // 尝试下一种格式
      }
    }
    
    // 所有格式都失败了，抛出最后一个错误
    if (lastError) {
      const msg = String(lastError.message || lastError);
      if (msg.includes('400')) {
        throw new Error('投票数据无效，请重试');
      } else if (msg.includes('401')) {
        throw new Error('请先登录后再投票');
      } else if (msg.includes('403')) {
        throw new Error('您没有权限进行投票');
      } else {
        throw lastError;
      }
    }
    
    throw new Error('投票失败，请重试');
  } catch (error) {
    console.error('投票失败:', error);
    throw error;
  }
};

// 获取排行榜（默认取全部投票，前端按 period 聚合），仅统计已关联画作且画作公开
export const getLeaderboard = async (_period: 'daily' | 'weekly' | 'monthly' | 'all' = 'all'): Promise<VotesResponse> => {
  // 直接请求包含必要关联字段的投票数据，并仅统计公开作品
  const params = new URLSearchParams({
    'pagination[page]': '1',
    'pagination[pageSize]': '500',
    'sort': 'createdAt:desc',
    'filters[drawing][isPublic][$eq]': 'true',
    // 选择性 populate，避免使用 * 导致校验或权限问题
    'populate[drawing][fields][0]': 'id',
    'populate[drawing][fields][1]': 'title',
    'populate[drawing][fields][2]': 'imageData',
    'populate[drawing][fields][3]': 'drawingType',
    'populate[drawing][fields][4]': 'isPublic',
    'populate[drawing][populate][user][fields][0]': 'id',
    'populate[drawing][populate][user][fields][1]': 'username',
    'populate[drawing][populate][user][fields][2]': 'email',
    'populate[user][fields][0]': 'id',
    'populate[user][fields][1]': 'username',
    'populate[user][fields][2]': 'email',
  });

  try {
    const response = await fetch(`${API_BASE_URL}/votes?${params}`, {
      method: 'GET',
      headers: createHeaders(),
    });

    let result: VotesResponse = await handleResponse(response);

    // 兜底：若 vote.user 缺失但 drawing.user 存在，则补齐
    const dataArr: any[] = (result as any)?.data || [];
    for (const v of dataArr) {
      if (!v?.user && v?.drawing?.user) {
        v.user = v.drawing.user;
      }
    }

    return normalizeVotesPayload<VotesResponse>(result);
  } catch (_e) {
    console.error('Error in getLeaderboard:', _e);
    // 返回空数据结构，前端显示“暂无排行数据”
    return { data: [], meta: { pagination: { page: 1, pageSize: 0, pageCount: 0, total: 0 } } } as unknown as VotesResponse;
  }
};

// 获取指定画作的总投票数（通过分页元数据 total 实现）
export const getDrawingVotes = async (drawingId: number): Promise<number> => {
  try {
    // 直接统计 votes 集合里与该 drawing 关联的记录数量，避免访问 /drawings/:id
    const params = new URLSearchParams({
      'filters[drawing][id][$eq]': drawingId.toString(),
      'pagination[page]': '1',
      'pagination[pageSize]': '1',
    });

    const response = await fetch(`${API_BASE_URL}/votes?${params}`, {
      method: 'GET',
      headers: createHeaders(),
    });
    const result: VotesResponse = await handleResponse(response);

    // Strapi v5 meta.pagination.total 可得总数；若无则回退为 data.length
    const total = (result as any)?.meta?.pagination?.total;
    if (typeof total === 'number') return total;
    const normalized = normalizeVotesPayload<VotesResponse>(result);
    return Array.isArray(normalized?.data) ? normalized.data.length : 0;
  } catch (error) {
    console.error('获取作品票数失败:', error);
    return 0;
  }
};